package com.lzx.hbh_system.service.zffyxxgl.Impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lzx.hbh_system.bo.filter.zffyxxgl.PayInfoFilter;
import com.lzx.hbh_system.bo.xqzhxxgl.HouseholdInfo;
import com.lzx.hbh_system.bo.zffyxxgl.ExpanseInfo;
import com.lzx.hbh_system.bo.zffyxxgl.HouseholdAExpanse;
import com.lzx.hbh_system.bo.zffyxxgl.PayInfo;
import com.lzx.hbh_system.bo.zffyxxgl.PayInfoDetail;
import com.lzx.hbh_system.bo.xqzhxxgl.HeatingInfo;
import com.lzx.hbh_system.dto.zffyxxgl.PayInfoDto;
import com.lzx.hbh_system.mapper.xqzhxxgl.HouseholdInfoMapper;
import com.lzx.hbh_system.mapper.zffyxxgl.ExpanseInfoMapper;
import com.lzx.hbh_system.mapper.zffyxxgl.HouseholdAExpanseMapper;
import com.lzx.hbh_system.mapper.zffyxxgl.PayInfoDetailMapper;
import com.lzx.hbh_system.mapper.zffyxxgl.PayInfoMapper;
import com.lzx.hbh_system.mapper.xqzhxxgl.HeatingInfoMapper;
import com.lzx.hbh_system.service.zffyxxgl.PayInfoService;
import com.lzx.hbh_system.util.SnowFlakeUtil;
import com.lzx.hbh_system.util.TurnDateToStringUtil;
import com.lzx.hbh_system.util.TurnStringToDateUtil;
import com.lzx.hbh_system.util.responseEntity.RespOutMsgHeader;
import com.lzx.hbh_system.util.responseEntity.ResponseView;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

@Service
@Slf4j
public class PayInfoServiceImpl extends ServiceImpl<PayInfoMapper, PayInfo> implements PayInfoService {
    @Autowired
    private PayInfoMapper payInfoMapper;
    @Autowired
    private ExpanseInfoMapper expanseInfoMapper;
    @Autowired
    private HouseholdInfoMapper householdInfoMapper;
    @Autowired
    private HeatingInfoMapper heatingInfoMapper;
    @Autowired
    private PayInfoDetailMapper payInfoDetailMapper;
    @Autowired
    private HouseholdAExpanseMapper householdAExpanseMapper;
    @Override
    public ResponseView queryAllPayInfoPageFilter(PayInfoFilter filter) {
        // 初始化返回视图
        // 校验参数
        ResponseView responseView = checkParams("00",filter);
        if(responseView.getRespOutMsgHeader().getRespCode().equals(500)){
            return responseView;
        }
        // 逻辑实现
        // 初始化分页对象
        Page<PayInfoDto> payInfoDtoPage = new Page<>(filter.getPageIndex(),filter.getPageSize());
        // 查询
        IPage<PayInfoDto> payInfoDtoIPage = payInfoMapper.selectAllPayInfoPageFilter(payInfoDtoPage,filter);
        // 处理结果集
        List<PayInfoDto> payInfoDtos = payInfoDtoIPage.getRecords();
        // 返回响应消息
        responseView.setRespOutMsgHeader(RespOutMsgHeader.success(payInfoDtos.size(),"查询成功！"));
        // 设置返回结果
        Map<String,Object> map = new HashMap<>();
        map.put("dataArray", payInfoDtos.toArray());
        map.put("currentPage",payInfoDtoIPage.getCurrent());
        map.put("totalsData",payInfoDtoIPage.getTotal());
        responseView.setMain(map);
        return responseView;
    }

    @Override
    public ResponseView queryAllCurrentQuarterPayInfoByHouseHoldCode(PayInfoFilter filter) {
        // 初始化返回视图
        // 校验参数
        ResponseView responseView = checkParams("00",filter);
        if(responseView.getRespOutMsgHeader().getRespCode().equals(500)){
            return responseView;
        }
        // 逻辑实现
        // 先获取所有获取相关的住户支付信息
        List<PayInfoDto> payInfoDtoList = payInfoMapper.selectAllPayInfoByHouseHold(filter);
        List<PayInfoDto> currentNotPayQuarterPayInfoDtoList = new ArrayList<>(); // 本季度支付信息列表 - 应收
        List<PayInfoDto> currentHasPaidQuarterPayInfoDtoList = new ArrayList<>(); // 本季度信息列表 - 已收
        List<PayInfoDto> otherQuarterPayInfoDtoList = new ArrayList<>(); // 非本季度的所有支付信息列表
        payInfoDtoList.forEach(item -> {
            if (verifyPayInfoHandler(item) && Objects.equals(item.getPayStatus(), "1")){
                // 已收 且 本季度
                currentHasPaidQuarterPayInfoDtoList.add(item);
            }else if(verifyPayInfoHandler(item) && Objects.equals(item.getPayStatus(), "0")){
                // 未收 且 本季度
                currentNotPayQuarterPayInfoDtoList.add(item);
            }else if(!verifyPayInfoHandler(item)){
                // 非本季度 - 历史
                otherQuarterPayInfoDtoList.add(item);
            }
        });
        // 返回响应消息
        responseView.setRespOutMsgHeader(RespOutMsgHeader.success("查询成功！"));
        // 设置返回结果
        Map<String,Object> map = new HashMap<>();
        map.put("NotPayQuarterPayInfoDtoList", currentNotPayQuarterPayInfoDtoList.toArray());
        map.put("HasPaidQuarterPayInfoDtoList",currentHasPaidQuarterPayInfoDtoList.toArray());
        map.put("HistoryPaidQuarterPayInfoDtoList",otherQuarterPayInfoDtoList.toArray());
        responseView.setMain(map);
        return responseView;

    }

    @Override
    public ResponseView queryAllHasPaidPayInfoByHouseHoldCode(PayInfoFilter filter) {
        // 初始化返回视图
        // 校验参数
        ResponseView responseView = checkParams("00",filter);
        if(responseView.getRespOutMsgHeader().getRespCode().equals(500)){
            return responseView;
        }
        // 逻辑实现
        // 先获取所有获取相关的住户支付信息
        List<PayInfoDto> payInfoDtoList = payInfoMapper.selectAllPayInfoByHouseHold(filter);
        List<PayInfoDto> hasPaidpayInfoDtoList = new ArrayList<>();
        payInfoDtoList.forEach(item -> {
            if(item.getPayStatus().equals("1")){
                hasPaidpayInfoDtoList.add(item);
            }
        });
        // 返回响应消息
        responseView.setRespOutMsgHeader(RespOutMsgHeader.success(hasPaidpayInfoDtoList.size(),"查询成功！"));
        responseView.setMain(hasPaidpayInfoDtoList.toArray());
        return responseView;
    }

    @Override
    public ResponseView processingPay(PayInfoFilter filter) {
        // 初始化返回视图
        // 校验参数
        ResponseView responseView = checkParams("02",filter);
        if(responseView.getRespOutMsgHeader().getRespCode().equals(500)){
            return responseView;
        }
        // 支付逻辑 模拟支付成功的回调
        List<PayInfo> payInfos = filter.getPayInfos();
        payInfos.forEach(item -> {
            item.setPayStatus("1"); // 模拟支付成功 设置已支付
            item.setPayTime(TurnDateToStringUtil.getTime()); // 设置支付时间
            item.setUpdateTime(TurnDateToStringUtil.getTime()); // 设置数据更新时间
            item.setPaidInAmount(item.getAmountReceivable()); // 设置 实收价格 为 应收价格
            // 更新支付详情
            UpdatePayInfoDetail(item,"2"); // 传输参数 - 设置未对账
            // 更新数据
            payInfoMapper.updateById(item);
         });
        // 更新住户状态
        UpdateHouseholdPayStatus(filter.getZhbh(),"1");
        // 返回响应消息
        responseView.setRespOutMsgHeader(RespOutMsgHeader.success("操作成功！"));
        return responseView;
    }

    @Override
    public ResponseView addBatchPayInfo(PayInfoFilter filter) {
        // 初始化返回视图
        // 校验参数
        ResponseView responseView = checkParams("03",filter);
        if(responseView.getRespOutMsgHeader().getRespCode().equals(500)){
            return responseView;
        }
        // 逻辑实现
        HouseholdInfo householdInfo = householdInfoMapper.selectById(filter.getZhbh()); // 拿到住户信息
        HeatingInfo heatingInfo = heatingInfoMapper.selectById(householdInfo.getHeatingCode());
        List<String> expanseIdList = filter.getExpanseIdList(); // 拿到费用项目信息编号
        expanseIdList.forEach(id -> {
            ExpanseInfo expanseInfo = expanseInfoMapper.selectById(id);
            // 计算应收金额
            BigDecimal amountReceivable = getAllPriceHandle(expanseInfo.getExpenseModle(),expanseInfo,heatingInfo.getHeatArea());
            // 生成支付信息Payinfo
            PayInfo payInfo = new PayInfo();
            Integer nowYear = Integer.valueOf(TurnDateToStringUtil.getTime("yyyy"));
            Integer nextYear = nowYear + 1;
            String key = SnowFlakeUtil.getId(); // 生成雪花Key
            payInfo.setId(key); // 生成主键
            payInfo.setPayStatus("0");
            payInfo.setPayReduction(new BigDecimal("0")); // 暂无优惠
            payInfo.setYearsBegin(nowYear);
            payInfo.setYearsEnd(nextYear);
            payInfo.setPaidInAmount(new BigDecimal("0")); // 暂无收款所以默认实际收取为零
            payInfo.setAmountReceivable(amountReceivable); // 设置 计算好的应收价格
            payInfo.setExpanseCode(id); // 设置每项费用项目ID
            payInfo.setCrateTime(TurnDateToStringUtil.getTime());
            payInfo.setHouseholdCode(householdInfo.getId()); // 设置住户编号
            payInfo.setLateFee(new BigDecimal("0")); // 暂不设置 滞纳金
            payInfo.setValiFlag("1"); // 默认有效
            // 保存信息
            payInfoMapper.insert(payInfo);
            // 生成一个支付详情信息-并设置默认未对账
            creatPayInfoDetail(payInfo,"2");
            // 生成一个中间表关联信息
            HouseholdAExpanse householdAExpanse = new HouseholdAExpanse();
            householdAExpanse.setExpanseId(id); // 设置中间表的费用项目关联编号
            householdAExpanse.setHouseHoldId(householdInfo.getId()); // 设置中间表的住户关联编号
            householdAExpanse.setValiFlag("1"); // 设置默认有效
            householdAExpanseMapper.insert(householdAExpanse);
        });
        // 返回响应消息
        responseView.setRespOutMsgHeader(RespOutMsgHeader.success("插入成功！"));
        // 设置返回结果
        return responseView;
    }

    @Override
    public ResponseView modifyBatchPayInfo(PayInfoFilter filter) {
        // 初始化返回视图
        // 校验参数
        ResponseView responseView = checkParams("02",filter);
        if(responseView.getRespOutMsgHeader().getRespCode().equals(500)){
            return responseView;
        }
        // 逻辑实现
        List<PayInfo> payInfos = filter.getPayInfos(); // 拿到一个或者多个支付信息
        payInfos.forEach(item -> {
            item.setUpdateTime(TurnDateToStringUtil.getTime()); // 设置更新时间
            if (Objects.equals(filter.getSfdz(), "1")){
                QueryWrapper<PayInfoDetail> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("pay_info_code",item.getId());
                PayInfoDetail payInfoDetail = payInfoDetailMapper.selectOne(queryWrapper);
                payInfoDetail.setReconciliationFlag("1");
                payInfoDetailMapper.updateById(payInfoDetail);
            }
            payInfoMapper.updateById(item);
        });
        // 返回响应消息
        responseView.setRespOutMsgHeader(RespOutMsgHeader.success("修改成功！"));
        // 设置返回结果
        return responseView;
    }

    @Override
    public ResponseView dropBatchPayInfo(PayInfoFilter filter) {
        // 初始化返回视图
        // 校验参数
        ResponseView responseView = checkParams("01",filter);
        if(responseView.getRespOutMsgHeader().getRespCode().equals(500)){
            return responseView;
        }
        // 逻辑实现
        List<String> payInfoIdList = filter.getPayInfoIdList(); // 拿到要删除的Id列表
        payInfoIdList.forEach(id -> {
            payInfoMapper.deleteById(id); // 删除支付信息
            QueryWrapper<PayInfoDetail> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("pay_info_code",id);
            payInfoDetailMapper.delete(queryWrapper); // 删除支付详情
        });
        // 返回响应消息
        responseView.setRespOutMsgHeader(RespOutMsgHeader.success("删除成功！"));
        // 设置返回结果
        return responseView;
    }

    /**
     * 判断支付信息是否为本季度支付信息
     * 相同返回 ture 不相同 返回 false
     * @param payInfoDto
     * @return
     */
    public Boolean verifyPayInfoHandler(PayInfoDto payInfoDto){
        // 获取当前系统时间对象
        Calendar date = Calendar.getInstance();
        // 获取当前对象的时间对象
        Calendar payInfoDate = Calendar.getInstance();
        payInfoDate.setTime(TurnStringToDateUtil.setStrToTime(payInfoDto.getCrateTime()));
        // 获取当前处于月份
        int currentMounth = date.get(Calendar.MONTH) + 1 ;
        int payInfoCreatMounth = payInfoDate.get(Calendar.MONTH) + 1 ;
        // 调用判断季度函数并返回是否同季度
        return verifyQuarter(currentMounth).equals(verifyQuarter(payInfoCreatMounth));
    }

    /**
     * 季度判断函数
     * @param verifyMounth 校验的月份
     * @return 返回季度说明字符串
     */
    public String verifyQuarter(int verifyMounth){
        String springQuarter = "3,4,5"; // 春
        String summerQuarter = "6,7,8"; // 夏
        String autumnQuarter = "9,10,11"; // 秋
        String winterQuarter = "12,1,2"; // 冬
        if(springQuarter.contains(String.valueOf(verifyMounth))){
            return "springQuarter";
        }else if(summerQuarter.contains(String.valueOf(verifyMounth))){
            return "summerQuarter";
        }else if(autumnQuarter.contains(String.valueOf(verifyMounth))){
            return "autumnQuarter";
        }else{
            return "winterQuarter";
        }
    }
    /**
     * 通过算法计算获得初始应收价格 - 默认无优惠
     * @param models 按计费模式、方式
     * @param expanseInfo 费用项目信息
     * @param heatArea 可供热面积
     * @return 初始应收价格 = 初始单价 x 可供热面积 （平方模式） 或者 初始应收价格 =  初始价格（固定）
     */
    public BigDecimal getAllPriceHandle(String models,ExpanseInfo expanseInfo,BigDecimal heatArea){

        BigDecimal amountPrice = expanseInfo.getAmountPrice(); // 获取单价
        if ("1".equals(models) ){
            //按平方
            BigDecimal amountReceivable = amountPrice.multiply(heatArea); // 单价 * 供热面积
            return amountReceivable;
        }else{
            //按固定
            BigDecimal amountReceivable = amountPrice; // 单价
            return amountReceivable;
        }
    }

    /**
     * 生成一个支付详情信息 - 未对账
     * @param verifyPayFlag 是否对账 标识
     * @param payInfo 支付信息
     */
    public void creatPayInfoDetail(PayInfo payInfo,String verifyPayFlag){
        // 初始化实体
        PayInfoDetail payInfoDetail = new PayInfoDetail();
        String key = SnowFlakeUtil.getId(); // 生成雪花Key
        payInfoDetail.setId(key); // 设置主键
        payInfoDetail.setPayInfoCode(payInfo.getId());
        payInfoDetail.setValiFlag("1"); // 默认有效
        payInfoDetail.setReconciliationFlag(verifyPayFlag); // 默认未对账
        // 保存消息
        payInfoDetailMapper.insert(payInfoDetail);
    }

    /**
     * 更新支付信息详情
     * @param payInfo 支付信息
     * @param verifyReconciliationFlag 对账标识
     */
    public void UpdatePayInfoDetail(PayInfo payInfo,String verifyReconciliationFlag){
        // 查询对应的详情信息
        QueryWrapper<PayInfoDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("pay_info_code",payInfo.getId());
        PayInfoDetail payInfoDetail = payInfoDetailMapper.selectOne(queryWrapper);
        payInfoDetail.setReconciliationFlag(verifyReconciliationFlag); // 设置对账标识
        // 保存信息
        payInfoDetailMapper.updateById(payInfoDetail);
    }

    /**
     * 修改住户的支付状态为 已缴
     * @param householdCode 更新的住户编号信息
     * @param verifyPayStatus 校验支付状态标识
     */
    public void UpdateHouseholdPayStatus(String householdCode,String verifyPayStatus){
        // 获取住户信息
        HouseholdInfo householdInfo = householdInfoMapper.selectById(householdCode);
        householdInfo.setHouseholdStatus("2"); // 设置住户状态 已缴费
        householdInfo.setPayStatus(verifyPayStatus); // 设置住户缴费状态 正常
        // 保存数据
        householdInfoMapper.updateById(householdInfo);
    }
    /**
     * 参数校验函数
     *  01 删除
     *  02 修改
     *  03 新增
     *  00 查询
     * @param filter
     * @return
     */
    public ResponseView checkParams(String operaType, PayInfoFilter filter){
        // 初始化返回视图
        ResponseView responseView = new ResponseView();
        if (Objects.equals(operaType, "01") && filter.getPayInfoIdList().size() == 0 ){
            responseView.setRespOutMsgHeader(RespOutMsgHeader.error("支付信息编号不能为空！"));
            return responseView;
        }
        else if (Objects.equals(operaType, "03")){
            if (filter.getZhbh() == null){
                responseView.setRespOutMsgHeader(RespOutMsgHeader.error("添加费用项目信息的住户编号不能为空！！"));
                return responseView;
            }
            if (filter.getExpanseIdList().size() == 0){
                responseView.setRespOutMsgHeader(RespOutMsgHeader.error("费用项目信息至少选择一种！"));
                return responseView;
            }
        }else if (Objects.equals(operaType, "02")){
            if (filter.getPayInfos().size() == 0){
                responseView.setRespOutMsgHeader(RespOutMsgHeader.error("修改的费用项目支付信息至少选择一种！"));
                return responseView;
            }
        }
        responseView.setRespOutMsgHeader(RespOutMsgHeader.success());
        return responseView;
    }
}
